﻿#region Copyright Jonathan Quiros

//	
// All rights are reserved. Reproduction or transmission in whole or in 
// part, in any form or by any means, electronic, mechanical or otherwise, 
// is prohibited without the prior written consent of the copyright owner.
//
// Filename: UsersController.cs
//

#endregion

using System;
using System.IO;
using System.Web.Mvc;
using Ids.Utils;
using Novagoal.Logic;
using Novagoal.Models;
using Novagoal.Utils;
using Novagoal.Website.Models.Forms;
using Novagoal.Website.Models.Views;
using Novagoal.Website.WebApp.Routing;

namespace Novagoal.Website.WebApp.Controllers
{
    public class UsersController : ListController
    {
        #region CONSTANTS

        private const string MALE_AVATAR = "~/Content/themes/custom-theme/images/male.png";
        private const string FEMALE_AVATAR = "~/Content/themes/custom-theme/images/female.png";

        #endregion

        #region PROPERTIES

        private readonly UsersLogic _usersLogic;
        private readonly RolesLogic _rolesLogic;
        private readonly PartiesLogic _partiesLogic;

        #endregion

        #region PUBLIC METHODS

        public UsersController(UsersLogic usersLogic, RolesLogic rolesLogic, PartiesLogic partiesLogic) : base(usersLogic)
        {
            _usersLogic = usersLogic;
            _rolesLogic = rolesLogic;
            _partiesLogic = partiesLogic;
        }

        [HttpGet]
        public ActionResult Index()
        {
            var users = _usersLogic.GetUsers(Request.Params, SortField, SortDirection, PageNumber, PageSize);

            var indexViewModel = new IndexViewModel
            {
                List = users,
                RouteValues = users.GetRouteValues(PageSize)
            };
            return View(indexViewModel);
        }

        [HttpPost]
        public ActionResult Index(FormCollection collection)
        {
            return Redirect(collection);
        }

        [HttpGet]
        public ActionResult Add()
        {
            var currentUser = GetUserInformation();
            var modelView = new UsersViewModel
            {
                Roles = _rolesLogic.GetRoles(currentUser.RoleId)
            };

            return View("Details"+currentUser.Person.Language, modelView);
        }

        [HttpGet]
        public ActionResult Edit(int id)
        {
            var currentUser = GetUserInformation();
            var user = _usersLogic.GetUser(id);
            var modelView = new UsersViewModel
                                {
                                    Roles = _rolesLogic.GetRoles(currentUser.RoleId)
                                };
            if(user == null)
            {
                modelView.Warnings.Add(string.Format("The user with id {0} doesn't exists", id));
            }
            else
            {
                modelView.UserId = user.Id;
                modelView.PersonId = user.Person.Id;
                modelView.FirstName = user.Person.FirstName;
                modelView.LastName = user.Person.LastName;
                modelView.EmailAddress = user.Person.EmailAddress;
                modelView.Enabled = user.Enabled;
                modelView.Role = user.Role;
                modelView.Gender = user.Person.Gender == Enums.Gender.Male.ToStringValue()
                                       ? Enums.Gender.Male
                                       : Enums.Gender.Female;
                modelView.Language = user.Person.Language == Enums.Language.English.ToStringValue()
                                         ? Enums.Language.English
                                         : Enums.Language.Español;
            }

            return View("Details"+currentUser.Person.Language, modelView);
        }

        [HttpGet]
        public ActionResult MyAccount()
        {
            var currentUser = GetUserInformation();
            var user = _usersLogic.GetUser(SecurityContext.User.Id);
            var modelView = new UsersViewModel
            {
                Roles = _rolesLogic.GetRoles(currentUser.RoleId)
            };
            if (user == null)
            {
                modelView.Warnings.Add(string.Format("The user with id {0} doesn't exists", SecurityContext.User.Id));
            }
            else
            {
                modelView.UserId = user.Id;
                modelView.PersonId = user.Person.Id;
                modelView.FirstName = user.Person.FirstName;
                modelView.LastName = user.Person.LastName;
                modelView.EmailAddress = user.Person.EmailAddress;
                modelView.Enabled = user.Enabled;
                modelView.Role = user.Role;
                modelView.Gender = user.Person.Gender == Enums.Gender.Male.ToStringValue()
                                       ? Enums.Gender.Male
                                       : Enums.Gender.Female;
                modelView.Language = user.Person.Language == Enums.Language.English.ToStringValue()
                                         ? Enums.Language.English
                                         : Enums.Language.Español;
            }

            return View("Details"+currentUser.Person.Language, modelView);
        }

        [HttpPost]
        public ActionResult Save(UserFormModel userFormModel)
        {
            var currentUser = GetUserInformation();
            var modelView = ModelViewFromForm(userFormModel);
            if(userFormModel.UserId == 0 && _usersLogic.UsernameExists(modelView.Person.EmailAddress))
            {
                ModelState.AddModelError("EmailAddress", "That username is already used");
            }
            if (ModelState.IsValid)
            {
                var user = ModelFromView(modelView);
                modelView.PersonId = user.Person.Id = _usersLogic.SavePerson(user.Person);
                modelView.UserId = _usersLogic.SaveUser(user);
                modelView.SuccessMessage = "User saved successfully";

                if (userFormModel.UserId == 0)
                {
                    var link = Url.Action("Activation", "Access",
                                          new {username = user.Person.EmailAddress, code = user.ActivationCode},
                                          Request.Url.Scheme);
                    _usersLogic.SendActivationMail(user, link);
                }
            }
            return View("Details"+currentUser.Person.Language, modelView);
        }

        [HttpGet]
        public FileContentResult GetAvatar(int personId)
        {
            var person = _usersLogic.GetPerson(personId);
            byte[] image;
            if(person == null || person.Avatar == null || person.Avatar.Length == 0)
            {
                var physicalPath =
                    Server.MapPath(person == null || person.Gender == Enums.Gender.Male.ToStringValue()
                                       ? MALE_AVATAR
                                       : FEMALE_AVATAR);
                var ms = new MemoryStream(FileToByteArray(physicalPath));
                image = ms.ToArray();
            }
            else
            {
                image = person.Avatar;
            }

            return File(image, "image/jpeg");
        }

        [HttpPost]
        public void SendActivationMail(int userId)
        {
            var user = _usersLogic.GetUser(userId);
            if(user != null)
            {
                var link = Url.Action("Activation", "Access",
                                          new { username = user.Person.EmailAddress, code = user.ActivationCode },
                                          Request.Url.Scheme);
                _usersLogic.SendActivationMail(user, link);
            }
        }

        // ReSharper disable Asp.NotResolved
        [HttpPost]
        public void SendJoinRequestMail(string email, int partyId)
        {
            var requester = _usersLogic.GetUser(email).Person;
            var party = _partiesLogic.GetParty(partyId);
            if(requester != null && party != null)
            {
                var link = Url.Action("View", "Parties", new { id = party.Id }, Request.Url.Scheme);
                _usersLogic.SendJoinRequestMail(requester, party, link);
            }
        }
        // ReSharper restore Asp.NotResolved

        [HttpPost]
        public void ChangeUserStatus(int userId, bool status)
        {
            _usersLogic.SetUserStatus(userId, status);
        }

        #endregion

        #region PRIVATE METHODS

        private UsersViewModel ModelViewFromForm(UserFormModel userFormModel)
        {
            var currentUser = GetUserInformation();
            var ms = new MemoryStream();
            if(userFormModel.Avatar != null) userFormModel.Avatar.InputStream.CopyTo(ms);

            return new UsersViewModel
                       {
                           Roles = _rolesLogic.GetRoles(currentUser.RoleId),
                           UserId = userFormModel.UserId,
                           Enabled = true,
                           Role = new Role
                                      {
                                          Id = userFormModel.RoleId
                                      },
                           Person = new Person
                                        {
                                            Id = userFormModel.PersonId,
                                            FirstName = userFormModel.FirstName,
                                            LastName = userFormModel.LastName,
                                            EmailAddress = userFormModel.EmailAddress,
                                            Gender = userFormModel.Gender.ToStringValue(),
                                            Language = userFormModel.Language.ToStringValue(),
                                            Avatar = ms.ToArray(),
                                            UpdatedBy = SecurityContext.User.Id
                                        }
                       };
        }

        private User ModelFromView(UsersViewModel modelView)
        {
            return new User
                       {
                           Id = modelView.UserId,
                           Enabled = modelView.Enabled,
                           Person = modelView.Person,
                           Role = modelView.Role,
                           UpdatedBy = SecurityContext.User.Id
                       };
        }

        /// <summary>
        /// Function to get byte array from a file
        /// </summary>
        /// <param name="fileName">File name to get byte array</param>
        /// <returns>Byte Array</returns>
        private byte[] FileToByteArray(string fileName)
        {
            byte[] buffer;

            try
            {
                // Open file for reading
                var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);

                // attach filestream to binary reader
                var binaryReader = new BinaryReader(fileStream);

                // get total byte length of the file
                var totalBytes = new FileInfo(fileName).Length;

                // read entire file into buffer
                buffer = binaryReader.ReadBytes((Int32)totalBytes);

                // close file reader
                fileStream.Close();
                fileStream.Dispose();
                binaryReader.Close();
            }
            catch (Exception)
            {
                return null;
            }

            return buffer;
        }

        #endregion
    }
}
